# -*- coding: utf-8 -*-
# Author: Sun Jiawei
# E-mail: sunjiawei@tbea.com
#
# 使用竞价空间作为特征进行日前电价预测
import datetime
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
from sklearn import linear_model
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_absolute_percentage_error, mean_squared_error
import seaborn as sns

df = pd.read_excel('./data/远景平台导出数据/日前信息_2022-03-01至2022-03-31.xlsx')

# 时间戳处理
columns = ['竞价空间-日前（MW）', '缩减前统一结算点电价-日前（元/MWh）']
x = df['时间戳']
x = x.map(lambda i: i.replace('24:00', '00:00'))
x = pd.to_datetime(x)
index = x[x.map(lambda i: i.hour == 0 and i.minute == 0)].index
x[index] = x[index].map(lambda i: i+datetime.timedelta(1))
y = df[columns]
y.columns = ['x', 'y']
# 画图
fig, ax = plt.subplots()
fig.autofmt_xdate(rotation=45)
ax.plot(x, y['x'], label='竞价空间')
ax2 = ax.twinx()
ax2.plot(x, y['y'], label='日前结算点电价', color='red')

ax.legend(loc='upper left')
ax.set_ylabel('MW')
ax.set_ylim(0, max(y['x']))

ax2.legend(loc='upper right')
ax2.set_ylabel('元/MWh')
ax2.set_ylim(0, max(y['y']))
plt.show()

# plt.subplots(figsize=(15, 15))
# fig = sns.heatmap(df[['统调负荷-日前（MW）', '外送联络线-日前（MW）', '新能源出力-日前（MW）',
#                       '竞价空间-日前（MW）', '缩减后节点电价-日前（元/MWh）', '缩减前节点电价-日前（元/MWh）',
#                       '缩减后统一结算点电价-日前（元/MWh）', '缩减前统一结算点电价-日前（元/MWh）']].corr(),
#                   vmax=1, square=True, cmap="Blues", fmt='.2g', annot=True)
# plt.show()

# 按照是否为出力高峰，增加一列特征
values = []
for t in x:
    if 10 <= t.hour <= 15:  # 出力高峰设定为上午10时到下午3时
        values.append(1)
    else:
        values.append(0)
y['x1'] = values
# 训练集、测试集划分
train_size = int(y.shape[0] * .8)
train_data = y.iloc[:train_size, :]
test_data = y.iloc[train_size:, :]
yuanjing_pred = df['缩减前节点电价-日前预测（元/MWh）'].iloc[train_size:]

reg = RandomForestRegressor(n_estimators=10)
reg.fit(train_data[['x', 'x1']], train_data['y'].tolist())

pred = reg.predict(test_data[['x', 'x1']])

# 计算MAPE前，先移除真实值为0的那些样本
y_true_index = []
for i in range(len(test_data)):
    if test_data['y'].iloc[i] != 0:
        y_true_index.append(i)
y_true = [test_data['y'].iloc[i] for i in y_true_index]
y_pred = [pred[i] for i in y_true_index]
y_pred_yuanjing = [yuanjing_pred.iloc[i] for i in y_true_index]
print(mean_absolute_percentage_error(y_true, y_pred))
print(mean_absolute_percentage_error(y_true, y_pred_yuanjing))

print(mean_squared_error(test_data['y'], pred))
print(mean_squared_error(test_data['y'], yuanjing_pred))


def plot_predict_and_true(y_true, y_pred):
    """绘制真实值与预测值的折线图

    Args:
        y_true(list): 真实值的列表
        y_pred(list): 预测值的列表

    Returns:
        None

    """
    fig, ax = plt.subplots()
    ax.plot(y_true, 'r', label='真实值')
    ax.plot(y_pred, '--g', label='预测值', alpha=0.7)

    ax.legend(loc='upper right')
    ax.set_ylabel('元/MWh')
    ax.set_ylim(0, max(max(y_true), max(y_pred)))
    plt.show()


plot_predict_and_true(test_data['y'].to_list(), pred)